/**
 * Copyright 2016-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.inmorn.extspring.controller;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;

import com.inmorn.extspring.metadata.ExportSetting;
import com.inmorn.extspring.metadata.GridModel;
import com.inmorn.extspring.metadata.QueryPage;
import com.inmorn.extspring.util.StringUtils;

public class BaseController extends JqGridBaseController{

	/**
	 * 用于判断是否为jsonResult返回值
	 */
	private boolean isJsonResult;
	protected Map<String, Object> jsonResult = new HashMap<String, Object>();
	
	/**
	 * 用于判断是否为页面分页请求返回
	 */
	private boolean isPageResult;
	
	protected final Logger logger = LoggerFactory.getLogger(getClass());
	
	//导出参数对象
	protected ExportSetting exportSetting;
	
	public static final String CONTENT_TYPE_FILE = "application/octet-stream";
	
	/**
	 * 前端AOP
	 */
	public void beforeInvoke(HttpServletRequest request,String requestUrl) {
		String[] urls = requestUrl.split("/");
		String method = urls[urls.length-1];
		
		if(StringUtils.startsWith(method, "search") || StringUtils.startsWith(method, "query")) {
			this.populateJqGridData(request);
			
			//创建QueryPage
			queryPage = new QueryPage(this.getRows(),this.getPage(),this.getSidx(),this.getSord());
		}
		//如果方法名是export
		else if(StringUtils.startsWith(method, "export")) {
			this.populateJqGridData(request);
			
			//创建ExportSetting
			exportSetting = new ExportSetting(this.getSidx(),this.getSord());
			
			this.populateExportData(request);
		}
	}
	
	
	/**
	 * 导出相关数据
	 */
	@SuppressWarnings("unchecked")
	public void populateExportData(HttpServletRequest request) {
		Map<String, String[]> parameters = request
				.getParameterMap();
		Set<String> keys = parameters.keySet();
		for (String key : keys) {
			String[] values = parameters.get(key);
			
			if(key.startsWith(ExportSetting.EXPORT_COL_NAMES)) {
				String seqStr = key.substring(ExportSetting.EXPORT_COL_NAMES.length());
				int seq = Integer.parseInt(seqStr);
				if (null != values && values.length > 0){
					exportSetting.addExportColName(seq, values[0]);
				}

			} else if (key.startsWith(ExportSetting.EXPORT_COL_MODELS)) {
				String seqStr = key.substring(ExportSetting.EXPORT_COL_MODELS.length());
				int seq = Integer.parseInt(seqStr);
				if (null != values && values.length > 0){
					exportSetting.addExportColModel(seq, values[0]);
				}
			} else if (key.startsWith(ExportSetting.EXPORT_COL_MODEL_LIST)){
				String seqStr = key.substring(ExportSetting.EXPORT_COL_MODEL_LIST.length());
				int seq = Integer.parseInt(seqStr);
				if (null != values && values.length > 0){
					try {
						JsonConfig config = new JsonConfig();
						config.setExcludes(new String[]{"editrules"});
						JSONObject json = JSONObject.fromObject(values[0], config);
						GridModel model = (GridModel) JSONObject.toBean(json, GridModel.class);
//						GridModel model = (GridModel) JSONObject.toBean(json, GridModel.class, config);
						if (StringUtils.isNotEmpty(model.getWidth()) && model.getWidth().indexOf("%") > 0) {
							model.setRealWidth(Float.floatToIntBits(Float.valueOf(model.getWidth()) * 1000));
						} else {
							model.setRealWidth(Integer.valueOf(model.getWidth()));
						}
						if (model.getEditoptions() != null) {
							String option = model.getEditoptions().getValue();
							String[] ms = option.split(";");
							HashMap<String, String> maps = new HashMap<String, String>(ms.length);
							for (String m : ms) {
								String[] d = m.split(":");
								if (d.length >= 2)
									maps.put(d[0].trim(), d[1].trim());
							}
							model.setMaps(maps);
						}
						exportSetting.addExportColModelList(seq, model);
					} catch (Exception e) {
						logger.error(e.getMessage(), e);
					}
				}

			} else if ("fileName".equals(key)) {
				if (null != values && values.length > 0){
					String fileName = values[0];
					try {
						fileName = new String(fileName.getBytes("GBK"),"ISO8859-1");
						exportSetting.setFileName(fileName);
					} catch (UnsupportedEncodingException e) {
						logger.error(e.getMessage(), e);
					} 
				}

			}
		}
	}	
	
	public void asyncExportResponse(HttpServletRequest request,HttpServletResponse response){
		try {
			String exportModule = "";
			if(exportSetting != null && StringUtils.isNotEmpty(exportSetting.getModule())){
				exportModule = exportSetting.getModule();
			}
			String nextAction = URLEncoder.encode("/export/exportfile/fileList_" + exportModule + ".action","utf-8");
			String successMessage = "main.success.exportfile";
			response.sendRedirect(request.getContextPath() + "/showSuccess?nextAction="
					+ nextAction + "&successMessage=" + successMessage);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public void downloadFile(HttpServletResponse response){
		downloadFile(response,CONTENT_TYPE_FILE);
	}
	
	public void downloadFile(HttpServletResponse response,String contentType){
		downloadFile(response,contentType,exportSetting.getFileName()
				,exportSetting.getRealName());
	}

	/**
	 * 下载文件
	 */
	public void downloadFile(HttpServletResponse response,String contentType
			,String fileName,String realName){
		try {
			String phisicalFileName = null;
			
			if (StringUtils.isNotEmpty(realName)) {
				phisicalFileName = realName;
			} 
			
			// tomcat对于GET请求并不会考虑使用request.setCharacterEncoding方法设置的编码，而会永远使用iso-8859-1编码。
			// 所以此判断是用于tomcat GET请求的处理，在WAS中不需要
			if (!Charset.defaultCharset().displayName().equalsIgnoreCase("UTF-8")) {
				fileName = new String(fileName.getBytes("ISO8859-1"), "UTF-8");
				phisicalFileName = new String(phisicalFileName.getBytes("ISO8859-1"), "UTF-8");
			}
			
			File file = new File(phisicalFileName);
			int contentLength = Integer.parseInt(file.length()+"");
			
			InputStream is = new FileInputStream(file);
			ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
	        byte[] buffer = new byte[1024]; 
	        int length = -1; 
	        try { 
	            while ((length = is.read(buffer)) != -1) { 
	                baos.write(buffer, 0, length); 
	            } 
	            baos.flush(); 
	        } catch (IOException e) { 
	            e.printStackTrace(); 
	        } 
	        try { 
	            is.close(); 
	            baos.close(); 
	        } catch (IOException e) { 
	            e.printStackTrace(); 
	        }
	        
			//TODO 需要先判断字符串是否是中文，如果国际化则需要使用其他编码方式
			fileName = new String(fileName.getBytes("GBK"), "ISO8859-1");
			phisicalFileName = new String(phisicalFileName.getBytes("GBK"), "ISO8859-1");
			
			OutputStream os = response.getOutputStream();
			response.setContentType(contentType + ",charset=ISO8859-1");
			response.setContentLength(contentLength);
			response.setHeader("Content-Disposition", "attachment;filename="
					+ ""+ new String((fileName).getBytes(),"utf-8"));
			
			os.write(baos.toByteArray());
			os.flush();
			os.close();
		} catch (Exception e) {
			logger.error("文件导出或下载失败！");
		}
	}
	
	public boolean isJsonResult() {
		return isJsonResult;
	}

	public void setJsonResult(boolean isJsonResult) {
		this.isJsonResult = isJsonResult;
	}

	public boolean isPageResult() {
		return isPageResult;
	}

	public void setPageResult(boolean isPageResult) {
		this.isPageResult = isPageResult;
	}

	public Map<String, Object> getJsonResult() {
		return jsonResult;
	}

	public void setJsonResult(Map<String, Object> jsonResult) {
		this.jsonResult = jsonResult;
	}
	/***
	 * 防止date form提交转换异常
	 * @param binder
	 */
	@InitBinder
	protected void initBinder(WebDataBinder binder) {
	    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	    binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
	}
}
